<template>
  <div class="p-6">
    <!-- 搜索/筛选栏 -->
    <a-space class="mb-4">
      <a-input v-model:value="filters.keyword" placeholder="搜索角色名" style="width: 200px" />
      <a-select v-model:value="filters.status" placeholder="状态" style="width: 120px" allow-clear>
        <a-select-option value="active">启用</a-select-option>
        <a-select-option value="disabled">禁用</a-select-option>
      </a-select>
      <a-button type="primary" @click="fetchRoles">搜索</a-button>
    </a-space>

    <!-- 批量操作 -->
    <a-space class="mb-2">
      <a-button type="primary" @click="() => batchUpdateStatus('active')"
        :disabled="!selectedRoles.length">批量启用</a-button>
      <a-button type="default" @click="() => batchUpdateStatus('disabled')"
        :disabled="!selectedRoles.length">批量禁用</a-button>
      <a-button type="dashed" danger @click="batchDelete" :disabled="!selectedRoles.length">批量删除</a-button>
    </a-space>

    <!-- 表格 -->
    <a-table :columns="columns" :data-source="filteredRoles" row-key="roleId" :row-selection="rowSelection" bordered
      :scroll="{ x: 600 }">
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'status'">
          <a-tag :color="record.status === 'active' ? 'green' : 'red'">
            {{ record.status === 'active' ? '启用' : '禁用' }}
          </a-tag>
        </template>

        <template v-else-if="column.key === 'permissions'">
          {{ record.permissions.length }}
        </template>

        <template v-else-if="column.key === 'action'">
          <a-space>
            <a-button type="link" @click.stop="toggleStatus(record)">
              {{ record.status === 'active' ? '禁用' : '启用' }}
            </a-button>
            <a-button type="link" @click.stop="openGrantModal(record)">授予权限</a-button>
            <a-button type="link" danger @click.stop="openDetails(record)">详情</a-button>
          </a-space>
        </template>

        <template v-else>
          {{ record[column.dataIndex] }}
        </template>
      </template>
    </a-table>

    <!-- 角色详情 -->
    <a-drawer title="角色详情" :open="showDetails" :width="500" @close="showDetails = false" placement="right">
      <div v-if="editRole">
        <p><strong>角色名：</strong>
          <a-input v-model:value="editRole.roleName" placeholder="请输入角色名" />
        </p>

        <p><strong>角色编码：</strong>
          <a-input v-model:value="editRole.roleCode" placeholder="请输入角色编码" />
        </p>

        <p>
          <strong>状态：</strong>
          <a-select v-model:value="editRole.status" style="width: 120px">
            <a-select-option value="active">启用</a-select-option>
            <a-select-option value="disabled">禁用</a-select-option>
          </a-select>
        </p>

        <p><strong>描述：</strong>
          <a-textarea v-model:value="editRole.description" :rows="3" placeholder="请输入描述" />
        </p>

        <p><strong>创建时间：</strong> {{ editRole.createdAt || '无' }}</p>

        <!-- 操作按钮 -->
        <a-space style="margin-top: 16px;">
          <a-button type="primary" @click="saveRole(editRole)">保存修改</a-button>
          <a-button type="primary" danger @click="deleteRole(editRole)">删除角色</a-button>
        </a-space>

        <p class="mt-4"><strong>权限列表：</strong></p>
        <ul>
          <li v-for="p in editRole.permissions" :key="p.permissionId">
            {{ p.permissionKey }} -- {{ p.description }}
          </li>
        </ul>
      </div>
    </a-drawer>
  </div>

  <!-- 授予权限弹窗 -->
  <a-modal v-model:open="showGrantModal" title="授予权限" @ok="handleGrantSave" :okButtonProps="{ disabled: !grantRole }"
    width="1000px">
    <!-- 服务筛选 -->
    <div style="margin-bottom: 16px; display: flex; justify-content: flex-end;">
      <a-select v-model:value="selectedServiceFilter" allowClear placeholder="按服务筛选" style="width: 200px">
        <a-select-option v-for="s in allServices" :key="s" :value="s">{{ s }}</a-select-option>
      </a-select>
    </div>

    <!-- 权限列表 -->
    <a-list :data-source="paginatedPermissions" bordered size="small" :pagination="{
      current: pagination.current,
      pageSize: pagination.pageSize,
      total: pagination.total as number,
      onChange: (page: number) => pagination.current = page
    }">
      <template #renderItem="{ item }">
        <a-list-item>
          <a-checkbox :checked="selectedPermissionIds.includes(item.permissionId)"
            @change="(e: CheckboxChangeEvent) => togglePermission(e, item.permissionId)">
            <b>{{ item.permissionKey }}</b> - {{ item.description }}
            <span style="color:#999">({{ item.serviceName }})</span>
          </a-checkbox>
        </a-list-item>
      </template>
    </a-list>
  </a-modal>
</template>
// e 就是 CheckboxChangeEvent
function togglePermission(e: CheckboxChangeEvent, id: string) {
if (e.target.checked) {
if (!selectedPermissionIds.value.includes(id)) {
selectedPermissionIds.value.push(id)
}
} else {
selectedPermissionIds.value = selectedPermissionIds.value.filter(x => x !== id)
}
}
<script setup lang="ts">
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { apiFetch } from '@/utils/request'
import { Modal, message } from 'ant-design-vue'

const identityurl = import.meta.env.VITE_API_IDENTITY

// ---------- 类型 ----------
interface Permission {
  permissionId: string
  permissionKey: string
  description: string
  serviceName?: string
}

interface Role {
  roleId: string
  roleCode: string
  roleName: string
  description: string
  status: 'active' | 'disabled'
  createdAt: string
  permissions: Permission[]
}

interface ApiResponse<T> {
  isSuccess: boolean
  errors: string[]
  data: T
}

// ---------- 状态 ----------
const roles = ref<Role[]>([])
const filters = ref({ keyword: '', status: '' })
const selectedRoles = ref<string[]>([])
const selectedRole = ref<Role | null>(null)
const showDetails = ref(false)

// 授权相关
const showGrantModal = ref(false)
const grantRole = ref<Role | null>(null)
const allPermissions = ref<Permission[]>([])
const selectedPermissionIds = ref<string[]>([])
const editRole = ref<Role | null>(null) // 用于表单编辑


// ---------- 生命周期 ----------
onMounted(() => fetchRoles())

// ---------- 数据获取 ----------
async function fetchRoles() {
  const query = new URLSearchParams(
    Object.entries(filters.value).reduce((acc, [k, v]) => {
      acc[k] = String(v)
      return acc
    }, {} as Record<string, string>)
  )

  const res = await apiFetch<ApiResponse<any[]>>(`${identityurl}/api/roles?${query}`)
  roles.value = res.data.map(r => ({
    roleId: r.id,
    roleCode: r.code,
    roleName: r.name,
    status: r.status ? 'active' : 'disabled',
    description: r.description,
    createdAt: r.createdAt,
    permissions: r.permissions.map((p: any) => ({
      permissionId: p.id,
      permissionKey: p.key,
      description: p.description,
      serviceName: p.serviceName
    }))
  }))
}

// 角色表格相关
const columns = [
  { title: '角色Code', dataIndex: 'roleCode', key: 'roleCode' },
  { title: '角色名', dataIndex: 'roleName', key: 'roleName' },
  { title: '角色说明', dataIndex: 'description', key: 'description' },
  { title: '权限数量', dataIndex: 'permissions', key: 'permissions' },
  { title: '状态', dataIndex: 'status', key: 'status' },
  { title: '操作', key: 'action' }
]
// ---------- 角色操作 ----------
function openDetails(role: Role) { selectedRole.value = role; editRole.value = { ...role, permissions: [...role.permissions] }, showDetails.value = true }
function toggleStatus(role: Role) { role.status = role.status === 'active' ? 'disabled' : 'active' }
function deleteRole(role: Role) { roles.value = roles.value.filter(r => r.roleId !== role.roleId) }
function batchUpdateStatus(status: 'active' | 'disabled') {
  roles.value.forEach(r => selectedRoles.value.includes(r.roleId) && (r.status = status))
}
function batchDelete() { roles.value = roles.value.filter(r => !selectedRoles.value.includes(r.roleId)); selectedRoles.value = [] }

// ---------- 授权逻辑 ----------
async function openGrantModal(role: Role) {
  grantRole.value = role
  showGrantModal.value = true

  const res = await apiFetch<ApiResponse<any[]>>(`${identityurl}/api/permissions/boundApi`)
  allPermissions.value = res.data.map(r => ({
    permissionId: r.id,
    permissionKey: r.key,
    description: r.description,
    serviceName: r.serviceName
  }))
  selectedPermissionIds.value = role.permissions.map(p => p.permissionId)
}

async function handleGrantSave() {
  if (!grantRole.value) return
  try {
    await apiFetch(`${identityurl}/api/roles/${grantRole.value.roleId}/permissions`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ permissionIds: selectedPermissionIds.value })
    })
    grantRole.value.permissions = allPermissions.value.filter(p => selectedPermissionIds.value.includes(p.permissionId))
    showGrantModal.value = false
  } catch (err) {
    console.error('授予权限失败', err)
  }
}

// ---------- 计算 ----------
const filteredRoles = computed(() =>
  roles.value.filter(r =>
    (!filters.value.keyword || r.roleName.includes(filters.value.keyword)) &&
    (!filters.value.status || r.status === filters.value.status)
  )
)

const rowSelection = computed(() => ({
  selectedRowKeys: selectedRoles.value,
  onChange: (keys: string[]) => selectedRoles.value = keys
}))

// 服务筛选

const allServices = computed(() => Array.from(new Set(allPermissions.value.map(p => p.serviceName).filter(Boolean))))

function togglePermission(e: CheckboxChangeEvent, id: string) {
  if (e.target.checked) {
    if (!selectedPermissionIds.value.includes(id)) {
      selectedPermissionIds.value.push(id)
    }
  } else {
    selectedPermissionIds.value = selectedPermissionIds.value.filter(x => x !== id)
  }
}


// 当前选择的服务过滤条件
const selectedServiceFilter = ref<string | undefined>(undefined)

// 根据选择过滤后的权限
const filteredPermissions = computed(() => {
  if (!selectedServiceFilter.value) {
    return allPermissions.value
  }
  return allPermissions.value.filter(p => p.serviceName === selectedServiceFilter.value)
})

// 分页数据基于过滤后的
const paginatedPermissions = computed(() => {
  const start = (pagination.current - 1) * pagination.pageSize
  const end = pagination.current * pagination.pageSize
  return filteredPermissions.value.slice(start, end)
})

// 分页总数也要用过滤后的
const pagination = reactive({
  current: 1,
  pageSize: 10,
  total: computed(() => filteredPermissions.value.length)
})

watch(selectedServiceFilter, () => {
  pagination.current = 1
})

import type { CheckboxChangeEvent } from 'ant-design-vue/es/checkbox/interface'


async function saveRole(role: Role) {
  if (!role) return

  try {
    // 调用后端接口更新角色信息
    const res = await apiFetch<ApiResponse<any>>(`${identityurl}/api/roles/${role.roleId}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        roleName: role.roleName,
        roleCode: role.roleCode,
        description: role.description,
        status: role.status === 'active'
      })
    })
   console.log(res)
    if (res.isSuccess) {
      // 用后端返回的 role 更新本地
      const updatedRole = res.data
      const index = roles.value.findIndex(r => r.roleId === role.roleId)
      if (index >= 0) {
        roles.value[index] = {
          roleId: updatedRole.id,
          roleCode: updatedRole.code,
          roleName: updatedRole.name,
          status: updatedRole.status ? 'active' : 'disabled',
          description: updatedRole.description,
          createdAt: updatedRole.createdAt,
          permissions: updatedRole.permissions?.map((p: any) => ({
            permissionId: p.id,
            permissionKey: p.key,
            description: p.description,
            serviceName: p.serviceName
          })) || []
        }
      }

      selectedRole.value = { ...editRole.value } as Role
    }
  } catch (err) {
    console.error(err)
    message.error('保存失败')
  }
}
</script>
